package com.duowan.cms.action;

import java.io.IOException;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.duowan.cms.common.exception.BaseCheckedException;
import com.duowan.cms.common.util.CompressUtil;
import com.duowan.cms.common.util.FileUtil;
import com.duowan.cms.common.util.PathUtil;
import com.duowan.cms.common.util.StringUtil;
import com.duowan.cms.common.util.ThreadUtil;
import com.duowan.cms.common.util.UrlUtil;
import com.duowan.cms.dto.channel.ChannelInfo;
import com.duowan.cms.dto.user.UserInfo;
import com.duowan.cms.service.channel.ChannelService;
import com.duowan.cms.service.file.FileAdapter;
import com.duowan.cms.service.file.FileService;
import com.duowan.cms.util.FileUploadHelper;


@Controller
public class FileController extends AbstractController {

	@Autowired
	private FileService fileService;
	
	@Autowired
	private ChannelService channelService;
	
	private static Logger logger = Logger.getLogger(FileController.class);

	@RequestMapping(value = "/file/fileManage", method = RequestMethod.GET)
	public String fileManage( HttpServletRequest request )throws IOException {
	    //目前所在频道
	    ChannelInfo channelInfo = (ChannelInfo)request.getSession().getAttribute("channelInfo");
	    String articleFilePath = channelInfo.getArticleFilePath();
	    String picFilePath =  channelInfo.getPicFilePath();
	    //所要访问的目录
        String toDirPath = request.getParameter("toDirPath");
        if (!StringUtil.isEmpty(toDirPath)) {   //有指定要访问的目录
            toDirPath = toDirPath.replace("\\", FileUtil.FILE_SEPARATOR);
            articleFilePath += toDirPath;
            picFilePath += toDirPath;
        }else{
            toDirPath = "/"; //默认访问专区的根目录
        }
        FileAdapter fileAdapter = new FileAdapter(articleFilePath, picFilePath);
        request.setAttribute("listFiles", fileService.sortFile(fileAdapter.listFiles()) );
        request.setAttribute("listFileStr", fileAdapter.listFileStr());
        request.setAttribute("realtivePath", toDirPath); //当前的相对路径
        //request.setAttribute("basePath", toDirPath); //当前的相对路径
        request.setAttribute("parentRealtivePath", this.getParentPath(toDirPath)); //上一级相对路径
        request.setAttribute("baseHtmlUrl", PathUtil.getDomainOncms(channelInfo.getId())); //访问html的基础URL(内网的)
        request.setAttribute("basePicUrl", PathUtil.getDomainOncms(channelInfo.getId())); //访问pic的基础URL(内网的)
        request.setAttribute("baseHtmlOnlineUrl", channelInfo.getDomain()); //访问html的基础URL(外网的)
        request.setAttribute("basePicOnlineUrl", channelInfo.getPicDomain()); //访问pic的基础URL(外网的)
        
        request.setAttribute("channelId", channelInfo.getId()); //访问pic的基础URL
        return "/file/file_manage";
	}

	

	
	@RequestMapping(value = "/file/download", method = RequestMethod.GET)
	public String download(HttpServletRequest request,HttpServletResponse response ) throws IOException {
		String path = request.getParameter("path");
		request.setAttribute("filePath", path);
		return "/file/download" ;
	}
	@RequestMapping(value = "/file/searchFile", method = RequestMethod.GET)
	public String searchFile(HttpServletRequest request,HttpServletResponse response ) throws IOException {
	    String searchPath = request.getParameter("currentPath");//当前目录
		String searchKey = request.getParameter("searchKey");//查找的文件名字
		ChannelInfo channelInfo = (ChannelInfo)request.getSession().getAttribute("channelInfo");
	    List<FileAdapter> listFiles = fileService.searchFileByName(new FileAdapter(channelInfo.getArticleFilePath()+searchPath, channelInfo.getPicFilePath()+searchPath), searchKey);
	    request.setAttribute("listFiles",  fileService.sortFile(listToArray(listFiles)));
	    request.setAttribute("parentRealtivePath", request.getParameter("parentRealtivePath") );//父目录
	    request.setAttribute("realtivePath", searchPath);//相对路径，默认是"/"
	    request.setAttribute("baseHtmlUrl", PathUtil.getDomainOncms(channelInfo.getId())); //访问html的基础URL(内网的)
        request.setAttribute("basePicUrl", PathUtil.getDomainOncms(channelInfo.getId())); //访问pic的基础URL(内网的)
        request.setAttribute("baseHtmlOnlineUrl", channelInfo.getDomain()); //访问html的基础URL(外网的)
        request.setAttribute("basePicOnlineUrl", channelInfo.getPicDomain()); //访问pic的基础URL(外网的)
        request.setAttribute("channelId", channelInfo.getId()); //访问pic的基础URL
		return "/file/file_manage";
	}
	
	private  FileAdapter[]  listToArray(List<FileAdapter> list){
		FileAdapter[] fileAdapterArr = new FileAdapter[list.size()];
		for (int i = 0; i < list.size(); i++) {
			fileAdapterArr[i] = list.get(i);
		}
		return fileAdapterArr;
	}
	
	@RequestMapping(value = "/file/createFolder", method = RequestMethod.GET)
	public String createFolder(HttpServletRequest request,HttpServletResponse response ) throws IOException {
	    ChannelInfo channelInfo = (ChannelInfo)request.getSession().getAttribute("channelInfo");
		String realtivePath = request.getParameter("realtivePath");
		String dirName = request.getParameter("dirName");
		String entirePath;
		if (dirName.indexOf("root/") == 0) {//以"root/"开头
			dirName = dirName.substring("root/".length()-1, dirName.length());
			entirePath = channelInfo.getArticleFilePath() + dirName ;
		}else{
			entirePath = channelInfo.getArticleFilePath() +realtivePath+ dirName ;
		}
		fileService.createFolder( FileUtil.getFilePath(entirePath) );
		return "redirect:/file/fileManage.do?toDirPath="+UrlUtil.encode(realtivePath);
	}
	
	@RequestMapping(value = "/file/deleteFile", method = RequestMethod.GET)
	public String deleteFile(HttpServletRequest request,HttpServletResponse response ) throws IOException, BaseCheckedException {
	    UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo");
	    ChannelInfo channelInfo = (ChannelInfo)request.getSession().getAttribute("channelInfo");
	    String realtivePath = request.getParameter("realtivePath");
        String deletePath = request.getParameter("deletePath");
        logger.info(userInfo.getUserId()+"删除["+channelInfo.getName()+"]频道的文件"+ FileUtil.getFilePath( channelInfo.getArticleFilePath()+realtivePath+deletePath));
        logger.info(userInfo.getUserId()+"删除["+channelInfo.getName()+"]频道的文件"+FileUtil.getFilePath(channelInfo.getPicFilePath()+realtivePath+deletePath));
		boolean isDeleteArticleFileSuccess = fileService.deleteFile(FileUtil.getFilePath(channelInfo.getArticleFilePath()+realtivePath+deletePath));
		boolean isDeletePicFileSuccess = fileService.deleteFile(FileUtil.getFilePath(channelInfo.getPicFilePath()+realtivePath+deletePath));
		if ( !(isDeleteArticleFileSuccess && isDeletePicFileSuccess) ) {
			throw new BaseCheckedException("", "删除文件失败：可能是由于权限问题，请联系系统管理员处理。");
		}
		return "redirect:/file/fileManage.do?toDirPath="+UrlUtil.encode(realtivePath);
	}
	
	@RequestMapping(value = "/file/upload", method = RequestMethod.POST)
	public void upload(HttpServletRequest request,HttpServletResponse response ) throws Exception {
		 if(!ServletFileUpload.isMultipartContent(request)){  
			 return ;
		 }

		 FileUploadHelper fileUploadHelper = new FileUploadHelper(request);
		 List<FileItem> fileItemList = fileUploadHelper.getFileItemList();
		 String currentPath = FileUtil.getFilePath( fileUploadHelper.getFieldValue("currentPath"));
		 //目前所在频道
	     ChannelInfo channelInfo = (ChannelInfo)request.getSession().getAttribute("channelInfo");
	     if (channelInfo == null) {
	    	 String channelId = fileUploadHelper.getFieldValue("channelId");
	    	 channelInfo = channelService.getById(channelId);
		}
	     String articleFilePath = channelInfo.getArticleFilePath();
	     String picFilePath =  channelInfo.getPicFilePath();
         for (int i = 0; i < fileItemList.size(); i++) {
        	  try {
        	      FileItem fileItem = fileItemList.get(i);
        	      if(fileItem==null)
        	          continue;
        	     String path = null;
        	      //根据上传文件的后缀名，自动判断要存放的路径
        	      if(FileUtil.isPicFormat(fileItem.getName()) && ( currentPath.indexOf(FileUtil.getFilePath("/s/")) == -1 )){
        	    	  path =  picFilePath + currentPath;
        	      }   else{
        	    	  path = articleFilePath + currentPath;
        	      }
        	      path = FileUtil.getFilePath(path);//统一文件目录分隔符
        	      fileService.writeFile(fileItemList.get(i), path);
        	      this.afterUpload( channelInfo.getId()  , currentPath ,path , fileItem.getName() );
        	      response.getWriter().write(FileUtil.isPicFormat(fileItem.getName())+";infoSeparator;" + fileItem.getName());
		      } catch (Exception e) {
		    	  logger.error("写文件时出错" , e);
				 throw e;
		      }
		  }
          //return "redirect:/file/fileManage.do?toDirPath="  + URLEncoder.encode(currentPath,"UTF-8");
	}

	/**
	 * 在上传后完成后，需要执行的事情
	 *  1.若是压缩包，自动解压后删除压缩文件,同步解压后的文件到外网，并把图片和非图片分开
	 *  2.若是文件，则自动把文件同步到外网。（注意：上传的文件已实现“图片和非图片分开”，上传时按文件后缀名来确定存储位置）
	 */
	private void afterUpload( String channelId, String currentPath,String path , String fileName  ) throws Exception{
	      String suffix = "";
	      if (fileName.indexOf(".") > -1) {
	    	  suffix = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length()).toLowerCase();
	    	  logger.info("文件名是"+fileName+",文件的后缀是" +suffix );
		  }
	      if("rar".equals(suffix) || "zip".equals(suffix)){
	    	  CompressUtil.deCompress( path  + fileName, path );
	    	  this.autoDispatchAndRyncFile(channelId,currentPath,  path,  fileName);
	      }else{
	    	  this.autoRyncFile(channelId, currentPath, path + fileName);
	      }
	}
	/**
	 * 同步到外网
	 */
	private void autoRyncFile(   final String channelIdFinal , final String currentPathFinal ,  final String pathFinal ){
		 ThreadUtil.getThreadPool().execute(new Runnable() {
				@Override
				public void run() {
					fileService.rsycFile(pathFinal, currentPathFinal, channelIdFinal);
				}
			});
		
	}
	/**
	 * 删除源文件，同步文件到外网，根据文件名把图片和非图片分开
	 * @param channelIdFinal	  频道ID
	 * @param currentPathFinal 当前路径相对于根路径 而得到的相对路径：用于计算当非根目录上传时，解压后的文件夹相对于上传目录的相对路径。
	 * 											 传入currentPathFinal是为了排除/s/目录,不作自动分发
	 * @param pathFinal             文件所在的当前路径 : 用于计算当在根目录上传时，解压后的文件夹相对于上传目录的相对路径。
	 * @param itemNameFinal   分发的文件名
	 */
	private void autoDispatchAndRyncFile( final String channelIdFinal , final String currentPathFinal , 
				final String pathFinal ,  final String itemNameFinal ){
    	  ThreadUtil.getThreadPool().execute(new Runnable() {
			@Override
			public void run() {
				  fileService.deleteFile(pathFinal + itemNameFinal);//删除上传的源文件
				  fileService.rsycFile(pathFinal, currentPathFinal, channelIdFinal);//同步文件到外网
				  fileService.dispatchFile( pathFinal, currentPathFinal, channelIdFinal);//把图片和非图片分开
			}
		});
	}
	


	/**
	 * 获取上一级目录，不存在时，返回null
	 * @param path
	 * @return
	 */
	private String getParentPath(String path){
	    if(StringUtil.isEmpty(path))
            return null;
	    path = path.replace("\\", FileUtil.FILE_SEPARATOR);
	    if(FileUtil.FILE_SEPARATOR.equals(path))
	        return null;
	    if(path.endsWith(FileUtil.FILE_SEPARATOR)){ //最后一位是分隔符
	        path = path.substring(0, path.lastIndexOf(FileUtil.FILE_SEPARATOR));
	    }
	    path = path.substring(0, path.lastIndexOf(FileUtil.FILE_SEPARATOR)+1);
	    return path;
	}
	
	
}
